home *** CD-ROM | disk | FTP | other *** search
/ Complete Linux / Complete Linux.iso / docs / apps / database / postgres / postgre4.z / postgre4 / src / lib / C / fcache.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-08-27  |  7.7 KB  |  297 lines

  1. /*---------------------------------------------------------------
  2.  * FILE:
  3.  *  fcache.c
  4.  *
  5.  * $Header: /private/postgres/src/lib/C/RCS/fcache.c,v 1.10 1992/08/21 05:39:35 mer Exp $
  6.  *
  7.  * Code for the 'function cache' used in Oper and Func nodes....
  8.  *
  9.  *---------------------------------------------------------------
  10.  */
  11. #include "tmp/c.h"
  12. #include "access/htup.h"
  13. #include "utils/catcache.h"
  14. #include "catalog/syscache.h"
  15. #include "catalog/pg_type.h"
  16. #include "catalog/pg_proc.h"
  17. #include "catalog/pg_language.h"
  18. #include "catalog/pg_relation.h"
  19. #include "parser/parsetree.h"
  20. #include "utils/fcache.h"
  21. #include "utils/log.h"
  22. #include "nodes/primnodes.h"
  23. #include "nodes/execnodes.h"
  24.  
  25.  
  26. static OID
  27. typeid_get_relid(type_id)
  28.         int type_id;
  29. {
  30.         HeapTuple     typeTuple;
  31.         TypeTupleForm   type;
  32.         OID             infunc;
  33.         typeTuple = SearchSysCacheTuple(TYPOID, (char *) type_id,
  34.                   (char *) NULL, (char *) NULL, (char *) NULL);
  35.         type = (TypeTupleForm) GETSTRUCT(typeTuple);
  36.         infunc = type->typrelid;
  37.         return(infunc);
  38. }
  39.  
  40.  
  41. /*-----------------------------------------------------------------
  42.  *
  43.  * Initialize the 'FunctionCache' given the PG_PROC oid.
  44.  *
  45.  *
  46.  * NOTE:  This function can be called when the system cache is being
  47.  *        initialized.  Therefore, use_syscache should ONLY be true
  48.  *        when the function return type is interesting (ie: set_fcache).
  49.  *-----------------------------------------------------------------
  50.  */
  51. #define FuncArgTypeIsDynamic(arg) \
  52.     (ExactNodeType(arg,Var) && get_varattno((Var)arg) == InvalidAttributeNumber)
  53.  
  54. ObjectId
  55. GetDynamicFuncArgType(arg, econtext)
  56.     Var arg;
  57.     ExprContext econtext;
  58. {
  59.     char *relname;
  60.     int rtid;
  61.     List rte;
  62.     HeapTuple tup;
  63.     Form_pg_relation pgc;
  64.     Form_pg_type  pgt;
  65.  
  66.     Assert(ExactNodeType(arg,Var));
  67.  
  68.     rtid = CInteger(CAR(get_varid(arg)));
  69.     relname = CString(getrelname(rtid, get_ecxt_range_table(econtext)));
  70.  
  71.     tup = SearchSysCacheTuple(TYPNAME, relname, NULL, NULL, NULL);
  72.     if (!tup)
  73.     elog(WARN,
  74.          "Lookup failed on type tuple for class %s",
  75.          &(pgc->relname.data[0]));
  76.  
  77.     return tup->t_oid;
  78. }
  79.  
  80. FunctionCachePtr
  81. init_fcache(foid, use_syscache, argList, econtext)
  82. ObjectId foid;
  83. Boolean use_syscache;
  84. LispValue argList;
  85. {
  86.     HeapTuple        procedureTuple;
  87.     HeapTuple        typeTuple;
  88.     Form_pg_proc     procedureStruct;
  89.     Form_pg_type     typeStruct;
  90.     FunctionCachePtr retval;
  91.     char             *tmp;
  92.     ObjectId         *funcname_get_funcargtypes();
  93.     int              nargs;
  94.  
  95.     /* ----------------
  96.      *   get the procedure tuple corresponding to the given
  97.      *   functionOid.  If this fails, returnValue has been
  98.      *   pre-initialized to "null" so we just return it.
  99.      * ----------------
  100.      */
  101.     retval = (FunctionCachePtr) palloc(sizeof(FunctionCache));
  102.  
  103.     if (!use_syscache)
  104.     elog(WARN, "what the ????, init the fcache without the catalogs?");
  105.  
  106.     procedureTuple = SearchSysCacheTuple(PROOID, (char *) foid,
  107.                                              NULL, NULL, NULL);
  108.  
  109.     if (!HeapTupleIsValid(procedureTuple))
  110.     elog(WARN,
  111.          "init_fcache: %s %d",
  112.          "Cache lookup failed for procedure", foid);
  113.  
  114.     /* ----------------
  115.      *   get the return type from the procedure tuple
  116.      * ----------------
  117.      */
  118.     procedureStruct = (Form_pg_proc) GETSTRUCT(procedureTuple);
  119.     
  120.     /* ----------------
  121.      *   get the type tuple corresponding to the return type
  122.      *   If this fails, returnValue has been pre-initialized
  123.      *   to "null" so we just return it.
  124.      * ----------------
  125.      */
  126.     typeTuple = SearchSysCacheTuple(TYPOID,
  127.                         (procedureStruct)->prorettype,
  128.                         NULL,
  129.                         NULL,
  130.                         NULL);
  131.  
  132.     if (!HeapTupleIsValid(typeTuple))
  133.     elog(WARN,
  134.          "init_fcache: %s %d",
  135.          "Cache lookup failed for type",
  136.          (procedureStruct)->prorettype);
  137.     
  138.     /* ----------------
  139.      *   get the type length and by-value from the type tuple and
  140.      *   save the information in our one element cache.
  141.      * ----------------
  142.      */
  143.     typeStruct = (Form_pg_type) GETSTRUCT(typeTuple);
  144.  
  145.     retval->typlen = (typeStruct)->typlen;
  146.     retval->typbyval = (typeStruct)->typbyval ? true : false ;
  147.     retval->foid = foid;
  148.     retval->language = procedureStruct->prolang;
  149.     retval->func_state = (char *)NULL;
  150.     retval->setArg     = NULL;
  151.     retval->hasSetArg  = false;
  152.     retval->oneResult  = ! procedureStruct->proretset;
  153.  
  154.     /*
  155.      * If we are returning exactly one result then we have to copy
  156.      * tuples and by reference results because we have to end the execution
  157.      * before we return the results.  When you do this everything allocated
  158.      * by the executor (i.e. slots and tuples) is freed.
  159.      */
  160.     if ((retval->language == POSTQUELlanguageId) &&
  161.     (retval->oneResult) &&
  162.     !(typeStruct->typbyval))
  163.     {
  164.     Form_pg_relation relationStruct;
  165.     HeapTuple        relationTuple;
  166.     TupleDescriptor  td;
  167.  
  168.     retval->funcSlot = (char *)MakeTupleTableSlot(true,
  169.                               true,
  170.                               NULL,
  171.                               InvalidBuffer,
  172.                               -1);
  173.     relationTuple = (HeapTuple)
  174.         SearchSysCacheTuple(RELNAME,
  175.                     (char *)&typeStruct->typname,
  176.                     (char *)NULL,
  177.                     (char *)NULL,
  178.                     (char *)NULL);
  179.  
  180.     if (relationTuple)
  181.     {
  182.         relationStruct = (Form_pg_relation)GETSTRUCT(relationTuple);
  183.         td = CreateTemplateTupleDesc(relationStruct->relnatts);
  184.     }
  185.     else
  186.         td = CreateTemplateTupleDesc(1);
  187.  
  188.     set_ttc_tupleDescriptor(((TupleTableSlot)retval->funcSlot), td);
  189.     }
  190.     else
  191.     retval->funcSlot = (char *)NULL;
  192.  
  193.     nargs = procedureStruct->pronargs;
  194.     retval->nargs = nargs;
  195.  
  196.     if (nargs > 0)
  197.     {
  198.     ObjectId *argTypes;
  199.  
  200.     retval->nullVect = (bool *)palloc((retval->nargs)*sizeof(bool));
  201.  
  202.     if (retval->language == POSTQUELlanguageId)
  203.     {
  204.         int  i;
  205.         List oneArg;
  206.         
  207.         retval->argOidVect =
  208.         (ObjectId *)palloc(retval->nargs*sizeof(ObjectId));
  209.         argTypes =
  210.         funcname_get_funcargtypes(&procedureStruct->proname.data[0]);
  211.         bcopy(argTypes,
  212.           retval->argOidVect,
  213.           (retval->nargs)*sizeof(ObjectId));
  214.  
  215.         for (i=0, oneArg = CAR(argList);
  216.          argList;
  217.          i++, argList = CDR(argList))
  218.         {
  219.         if (FuncArgTypeIsDynamic(oneArg))
  220.             retval->argOidVect[i] = GetDynamicFuncArgType(oneArg,
  221.                                   econtext);
  222.         }
  223.     }
  224.     else
  225.         retval->argOidVect = (ObjectId *)NULL;
  226.     }
  227.     else
  228.     {
  229.     retval->argOidVect = (ObjectId *)NULL;
  230.     retval->nullVect = (BoolPtr)NULL;
  231.     }
  232.  
  233.     /*
  234.      * XXX this is the first varlena in the struct.  If the order
  235.      *     changes for some reason this will fail.
  236.      */
  237.     if (procedureStruct->prolang == POSTQUELlanguageId)
  238.     {
  239.     retval->src = (char *) textout(&(procedureStruct->prosrc));
  240.     retval->bin = (char *) NULL;
  241.     }
  242.     else
  243.     {
  244. #if 0
  245.     /*
  246.      * I'm not sure that we even need to do this at all.
  247.      */
  248.         tmp = (char *)
  249.         SearchSysCacheGetAttribute(PROOID,
  250.                        Anum_pg_proc_probin,
  251.                        foid);
  252.         retval->bin = (char *) textout(tmp);
  253. #endif 
  254.         retval->bin = (char *) NULL;
  255.     retval->src = (char *) NULL;
  256.     }
  257.  
  258.     if (retval->language != POSTQUELlanguageId)
  259.     fmgr_info(foid, &(retval->func), &(retval->nargs));
  260.     else
  261.     retval->func = (func_ptr)NULL;
  262.  
  263.  
  264.     return(retval);
  265. }
  266.  
  267. void
  268. set_fcache(node, foid, argList, econtext)
  269.  
  270. Node node;
  271. ObjectId foid;
  272. LispValue argList;
  273. ExprContext econtext;
  274.  
  275. {
  276.     Func fnode;
  277.     Oper onode;
  278.     FunctionCachePtr fcache, init_fcache();
  279.  
  280.     fcache = init_fcache(foid, true, argList, econtext);
  281.  
  282.     if (IsA(node,Oper))
  283.     {
  284.         onode = (Oper) node;
  285.         onode->op_fcache = fcache;
  286.     }
  287.     else if (IsA(node,Func))
  288.     {
  289.         fnode = (Func) node;
  290.         fnode->func_fcache = fcache;
  291.     }
  292.     else
  293.     {
  294.         elog(WARN, "init_fcache: node must be Oper or Func!");
  295.     }
  296. }
  297.